

class Waterfall {

    constructor() {
        this._currentIndex = 0;
        this._waterfallBox = null; // 瀑布流容器元素
        this._wRowDomObjArr = []; // 存储每一列的DOM对象和当前高度的数组
        this._imgDomObjArr = []; // 存储所有图片DOM对象的数组
        this._minWRowDomObj = null; // 当前最小高度的列
        this._row = 0; // 列数
        // onscroll 每次触底触发增加 1
    }

    // 页面加载完成触发
    onLoad() {
        this._waterfallBox = document.querySelector(".waterfall-box"); // 获取瀑布流容器
        this._setRow(); // 设置列数
        this._showCards(); // 显示图片
    }

    // 页面大小更改触发
    onResize() {
        this._setRow() // 重新设置列数
        this._showCards(); // 重新显示图片
    }

    // 设置列
    _setRow() {
        let newRow = this._getRow(); // 获取新的列数
        if (this._row !== newRow) { // 如果列数发生变化
            this._waterfallBox.innerHTML = ""; // 清空容器
            this._currentIndex = 0; // 重置图片索引
            // 当重新设置列数时，可以初始化需渲染的高度或者不初始化

            this._row = newRow; // 更新列数
            this._wRowDomObjArr = []; // 清空列数组
            for (let i = 0; i < this._row; i++) { // 创建新的列
                this._wRowDomObjArr[i] = this._getWRowDomObj();
                this._wRowDomObjArr[i].height = 0; // 初始化高度为0
                this._waterfallBox.appendChild(this._wRowDomObjArr[i].dom); // 将列添加到容器中
            }
        }
    }

    // 获取列数
    _getRow() {
        const w = this._waterfallBox.offsetWidth; // 获取容器宽度
        if (w < 600) {
            return 1; // 如果宽度小于600，设置1列
        } else if (w < 980) {
            return 2; // 如果宽度小于980，设置2列
        } else if (w < 1280) {
            return 3; // 如果宽度小于1280，设置3列
        }
        return 3; // 默认设置3列
    }

    // 是否还需渲染 card
    _canDraw() {
        this._minWRowDomObj = this._wRowDomObjArr.reduce((accumulator, item) => { // 找到当前最小高度的列
            return accumulator.dh <= item.dh ? accumulator : item;
        }, this._wRowDomObjArr[0]);
        // 需要达到的高度 h , 才停止新的 card 渲染;
        // 需要渲染到的高度 = 屏幕的高度 * this._scrollNum, 每触发一次增加1屏幕高度的 card
        let h = parseInt(document.documentElement.clientHeight) * this._scrollNum;
        if (parseInt(this._minWRowDomObj.dom.offsetHeight) < h) { // 如果最小高度列的高度小于需要渲染的高度，则继续渲染
            return true;
        }
        return false; // 否则，停止渲染
    }

    // 渲染展示图片
    _showCards() {
        if (this._canDraw()) { // 检查是否需要继续渲染图片
            if (!!this._imgDomObjArr[this._currentIndex]) {
                this._minWRowDomObj.dh += this._imgDomObjArr[this._currentIndex].obj.height; // 增加最小高度列的高度
                this._minWRowDomObj.dom.appendChild(this._imgDomObjArr[this._currentIndex].dom); // 将图片添加到DOM中
                this._currentIndex++; // 移动到下一张图片
                this._showCards(); // 递归调用，继续渲染
                return;
            }

            // 从模拟数据中获取图片对象
            Mock.getCurrentImgObjPromise(this._currentIndex).then(imgObj => {
                if (!imgObj) {
                    return;
                }
                this._imgDomObjArr.push(this._getImgDomObj(imgObj)); // 创建图片DOM对象并添加到数组
                this._minWRowDomObj.dh += imgObj.height; // 增加最小高度列的高度
                this._minWRowDomObj.dom.appendChild(this._imgDomObjArr[this._currentIndex].dom); // 将图片添加到DOM中
                this._currentIndex++; // 移动到下一张图片
                this._showCards(); // 递归调用，继续渲染
            })
        }
    }

    // 返回 wRowDomObj 
    _getWRowDomObj() {
        return {
            dom: this._getWFRowDom(), // 获取新建的列DOM对象
            dh: 0 // 初始化高度为0
        }
    }

    // 返回 imgDomObj
    _getImgDomObj(imgObj) {
        let h = parseInt(imgObj.height / imgObj.width * this._wRowDomObjArr[0].dom.offsetWidth); // 计算图片高度
        imgObj.height = h; // 更新图片对象的高度
        return {
            dom: this._getCardDom(imgObj.imgName, h), // 获取新建的图片卡片DOM对象
            obj: imgObj // 图片对象
        }
    }

    // 获取新建的 waterfallRow 节点
    _getWFRowDom() {
        const wFRowDom = document.createElement("div"); // 创建新的列DOM对象
        wFRowDom.classList.add("waterfall-row"); // 添加类名
        return wFRowDom;
    }

    // 获取新建的 card 节点
    _getCardDom(imgName, height) {
        const card = document.createElement("div"); // 创建新的卡片DOM对象
        const img = document.createElement("img"); // 创建图片元素
        card.classList.add("card"); // 添加类名
        card.style.height = `${height}px`; // 设置卡片高度
        img.src = `./images/${imgName}`; // 设置图片源
        img.alt = ""; // 设置图片替代文本

        img.onload = () => { // 图片加载完成后的回调函数
            card.style.height = "auto"; // 将卡片高度设置为自动
        }
        card.appendChild(img); // 将图片元素添加到卡片中
        return card;
    }

}